package com.itheima.restkeeper.handler.wchat;

import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPay;
import com.itheima.restkeeper.constant.SuperConstant;
import com.itheima.restkeeper.constant.TradingCacheConstant;
import com.itheima.restkeeper.enums.PaySettingEnum;
import com.itheima.restkeeper.enums.TradingEnum;
import com.itheima.restkeeper.exception.ProjectException;
import com.itheima.restkeeper.handler.ITradingHandler;
import com.itheima.restkeeper.handler.wchat.config.WXPayConfigCustom;
import com.itheima.restkeeper.pojo.Trading;
import com.itheima.restkeeper.req.TradingSettingVo;
import com.itheima.restkeeper.req.TradingVo;
import com.itheima.restkeeper.service.ITradingService;
import com.itheima.restkeeper.utils.BeanConv;
import com.itheima.restkeeper.utils.EmptyUtil;
import com.itheima.restkeeper.utils.ExceptionsUtil;
import com.itheima.restkeeper.utils.ShowApiService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description:
 * @Version: V1.0
 */
@Service("wchatPayTradingHandler")
@Slf4j
public class WchatPayTradingHandlerImpl implements ITradingHandler {
    @Autowired
    RedissonClient redissonClient;

    @Autowired
    ITradingService tradingService;

    @Autowired
    ShowApiService showApiService;

    @Override
    public TradingVo doPay(TradingVo tradingVo) throws ProjectException {
        try {
            WXPay wxPay = getConfig(tradingVo);
            //4、调用微信API NATIVE支付【1】：支付的备注
            Map<String, String> data = new HashMap<String, String>();
            data.put("body", "餐掌柜-餐饮消费");
            data.put("out_trade_no", String.valueOf(tradingVo.getTradingOrderNo()));
            data.put("device_info", "");
            data.put("fee_type", "CNY");
            // 支付金额 单位：分， 元*100 --> 分
            // 支付金额必须是 整型 *** 重要
            // 建议： String.valueOf()
            data.put("total_fee",
                    String.valueOf(tradingVo.getTradingAmount().multiply(new BigDecimal("100")).intValue()));
            data.put("spbill_create_ip", "123.12.12.123");
            data.put("notify_url", "http://itheima.ngrok2.xiaomiqiu.cn/wxpay/notify");
            data.put("trade_type", "NATIVE");  // NATIVE 指定为扫码支付  JSAPI 网站支付
            Map<String, String> resp = wxPay.unifiedOrder(data);
            //5、受理结果【只表示请求是否成功，而不是支付是否成功】

            //5.1、受理成功：修改交易单
            if (!EmptyUtil.isNullOrEmpty(resp)
                    && resp.get("return_code").equals("SUCCESS")
                    && resp.get("result_code").equals("SUCCESS")){
                String subCode = resp.get("result_code");
                String subMsg = resp.get("code_url");
                if (EmptyUtil.isNullOrEmpty(subMsg)) {
                    throw new ProjectException(TradingEnum.FACE_TO_FACE_FAIL);
                }
                //5.2、指定统一下单code
                tradingVo.setPlaceOrderCode(subCode);
                //5.3、指定统一下单返回信息
                tradingVo.setPlaceOrderMsg(subMsg);
                //5.4、指定统一下单json字符串
                tradingVo.setPlaceOrderJson(JSONObject.toJSONString(resp));
                //5.5、指定交易状态
                tradingVo.setTradingState(SuperConstant.FKZ);
                //5.6、指定非退款交易
                tradingVo.setIsRefund(SuperConstant.NO);
                Trading trading = BeanConv.toBean(tradingVo, Trading.class);
                //5.7、重新保存信息
                boolean flag = tradingService.saveOrUpdate(trading);
                if (!flag){
                    throw new ProjectException(TradingEnum.SAVE_OR_UPDATE_FAIL);
                }
                //6、生成二维码，返回结果
                String imgUrl = showApiService.handlerQRcode(tradingVo.getPlaceOrderMsg());
                TradingVo tradingVoResult = BeanConv.toBean(trading, TradingVo.class);
                tradingVoResult.setImgUrl(imgUrl);
                return tradingVoResult;
            }else {
                throw new ProjectException(TradingEnum.FACE_TO_FACE_FAIL);
            }
        } catch (Exception e) {
            log.error("微信统一下单失败：{}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(TradingEnum.FACE_TO_FACE_FAIL);
        }
    }

    /**
     * 获取微信配置对象
     * @param tradingVo
     * @return
     */
    private WXPay getConfig(TradingVo tradingVo) throws Exception {
        //1、从redis中获取当前企业支付config
        String key = TradingCacheConstant.REDIS_GROUP+ PaySettingEnum.WCHART.getType() +":"+tradingVo.getEnterpriseId();
        RBucket<TradingSettingVo> bucket = redissonClient.getBucket(key);
        TradingSettingVo settingVo = bucket.get();
        //2、容器如果为空，抛出异常
        if (EmptyUtil.isNullOrEmpty(settingVo)){
            throw  new ProjectException(TradingEnum.ENTERPRISEID_EMPT);
        }
        //3、Factory使用配置
        WXPayConfigCustom config = BeanConv.toBean(settingVo, WXPayConfigCustom.class);
        WXPay wxpay = new WXPay(config);
        return wxpay;
    }

    @Override
    public TradingVo queryPay(TradingVo tradingVo) {
        try {
            WXPay wxPay = getConfig(tradingVo);
            //4、调用微信API：通用查询支付情况
            Map<String, String> data = new HashMap<String, String>();
            data.put("out_trade_no", String.valueOf(tradingVo.getTradingOrderNo()));
            Map<String, String> result = wxPay.orderQuery(data);
            //5、响应成功，分析交易状态
            if (!EmptyUtil.isNullOrEmpty(result)
                    && result.get("return_code").equals("SUCCESS")
                    && result.get("result_code").equals("SUCCESS")){
                //当前交易状态：

                String tradeStatus = result.get("trade_state");
                boolean flag = false;
                //5.1、未付款交易超时关闭，或支付完成后全额退款
                if (SuperConstant.WX_CLOSED.equals(tradeStatus)){
                    tradingVo.setTradingState(SuperConstant.QXDD);
                    flag= true;
                }
                //5.2、交易支付成功
                if (SuperConstant.WX_SUCCESS.equals(tradeStatus)){
                    tradingVo.setTradingState(SuperConstant.YJS);
                    flag= true;
                }
                //6、修改交易单状态
                if (flag){
                    tradingVo.setResultCode(result.get("return_code"));
                    tradingVo.setResultMsg(result.get("return_msg"));
                    tradingVo.setResultJson(JSONObject.toJSONString(result));
                    Trading trading = BeanConv.toBean(tradingVo, Trading.class);
                    Boolean flagSaveOrUpdate = tradingService.saveOrUpdate(trading);
                    if (!flagSaveOrUpdate){
                        throw new ProjectException(TradingEnum.SAVE_OR_UPDATE_FAIL);
                    }
                    //7、返回结果
                    return BeanConv.toBean(trading, TradingVo.class);
                }
            }else {
                throw new ProjectException(TradingEnum.QUERY_FACE_TO_FACE_FAIL);
            }
        } catch (Exception e) {
            log.error("查询微信统一下单失败：{}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(TradingEnum.QUERY_FACE_TO_FACE_FAIL);
        }
        return null;
    }
}
